// Copyright  Author(https://github.com/LiuShuKu). All Rights Reserved.

// Copyright (c)  2024 LiuShuKu
// Project Name :   balance
// Author       :   liushuku@yeah.net

// Package tron .
package tron

import (
	"context"
	"fmt"
	"github.com/fbsobreira/gotron-sdk/pkg/proto/core"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/shopspring/decimal"
	"math/big"
	"strconv"
	"time"
	"tronServer/internal/model/domain"
)

const (
	// 交易详情
	transactionInfoURL = "%s/transaction-info?hash=%s"
	// 交易详情列表
	transactionListInfoURL = "%s/new/token_trc20/transfers"
)

type tronQuery struct {
}

var Query = &tronQuery{}

// GetUsdtTransactionDetails 获取Usdt交易记录根据UsdtAddress
func (t *tronQuery) GetUsdtTransactionDetails(ctx context.Context, usdtAddress string) (details *domain.UsdtTransactionDetailListData, err error) {
	var (
		// TODO 时间
		now = time.Now()
		//startTime = strconv.FormatInt(now.Add(-time.Hour).UnixMilli(), 10)
		endTime   = strconv.FormatInt(now.Add(time.Hour).UnixMilli(), 10)
		startTime = "1715443200000"
		//endTime        = "1716018079000"
		size           = 0
		limit          = 50
		detailData     *domain.UsdtTransactionDetailListData
		tokenTransfers []*domain.TokenTransfers
	)
	// 持续性获取数据
	for {
		if detailData, err = t.fetchData(ctx, usdtAddress, startTime, endTime, strconv.Itoa(size), strconv.Itoa(limit)); err != nil {
			break
		}
		// 校验数据
		if detailData == nil || detailData.TokenTransfers == nil {
			g.Log().Infof(ctx, "当前钱包 %s ->  未查询到交易数据", usdtAddress)
			return
		}
		for _, transfer := range detailData.TokenTransfers {
			if transfer.ToAddress == usdtAddress && transfer.ContractRet == "SUCCESS" && transfer.FinalResult == "SUCCESS" {
				if transfer.TokenInfo.TokenID == contract {
					// 添加数据
					tokenTransfers = append(tokenTransfers, transfer)
				} else {
					g.Log().Infof(ctx, "当前钱包 %v ->  查询到 %v 非USDT交易数据", usdtAddress, transfer)
				}
			}
		}
		// 翻页
		size++
		// 翻页结束
		if size*limit > detailData.Total {
			break
		}
	}
	g.Log().Infof(ctx, "当前钱包 %v -> 共查询到 %v 条", usdtAddress, len(tokenTransfers))
	// 重新赋值
	{
		detailData.TokenTransfers = tokenTransfers
		details = detailData
	}
	return
}

// GetTrxTransactionDetailsTxId 获取Trx 交易详情
func (t *tronQuery) GetTrxTransactionDetailsTxId(ctx context.Context, txId string) (detail *domain.TrxTransactionDetails, err error) {
	client := tronHttp.connect()
	err = client.http.GetVar(ctx, fmt.Sprintf(transactionInfoURL, client.url, txId)).Scan(&detail)
	return
}

// GetUsdtTransactionDetailsTxId 获取Usdt 交易详情
func (t *tronQuery) GetUsdtTransactionDetailsTxId(ctx context.Context, txId string) (detail *domain.UsdtTransactionDetails, err error) {
	client := tronHttp.connect()
	err = client.http.GetVar(ctx, fmt.Sprintf(transactionInfoURL, client.url, txId)).Scan(&detail)
	return
}

// GetTrxBalance 获取账号的Trx余额
func (t *tronQuery) GetTrxBalance(ctx context.Context, trc20Address string) (trxBalance string, err error) {
	var (
		balance decimal.Decimal
	)

	if balance, err = t.balance(ctx, trc20Address, typeTrx); err != nil {
		return
	}
	trxBalance = balance.String()
	return
}

// GetUsdtBalance 获取账号的Usdt余额
func (t *tronQuery) GetUsdtBalance(ctx context.Context, trc20Address string) (usdtBalance string, err error) {
	var (
		balance decimal.Decimal
	)

	if balance, err = t.balance(ctx, trc20Address, typeUsdt); err != nil {
		return
	}
	usdtBalance = balance.String()
	return
}

// balance 获取账号的余额
func (t *tronQuery) balance(ctx context.Context, trc20Address string, queryType int) (balance decimal.Decimal, err error) {
	var (
		grpcClient  *tronGrpcs
		trxAccount  *core.Account
		usdtAccount *big.Int
	)
	// 获取 grpcClient
	if grpcClient, err = tronGrpc.connect(ctx); err != nil {
		return
	}
	// 关闭 grpcClient
	defer func() {
		grpcClient.stop()
	}()
	// 查询余额
	switch queryType {
	case typeUsdt:
		if usdtAccount, err = grpcClient.grpc.TRC20ContractBalance(trc20Address, contract); err != nil {
			return
		}
		balance = decimal.NewFromBigInt(usdtAccount, 0).Div(decimal.NewFromInt(tronUnit))
	case typeTrx:
		if trxAccount, err = grpcClient.grpc.GetAccount(trc20Address); err != nil {
			return
		}
		balance = decimal.NewFromInt(trxAccount.Balance).Div(decimal.NewFromInt(tronUnit))
	}
	return
}

// fetchData 获取交易数据
func (t *tronQuery) fetchData(ctx context.Context, usdtAddress, startTime, endTime, size, limit string) (detailData *domain.UsdtTransactionDetailListData, err error) {
	// 获取http客户端
	client := tronHttp.connect(time.Second * 15)
	// 构建参数
	param := g.Map{
		"start":            size,
		"limit":            limit,
		"contract_address": contract,
		"start_timestamp":  startTime,
		"end_timestamp":    endTime,
		"relatedAddress":   usdtAddress,
		"confirm":          "true",
	}
	// 发送请求
	err = client.http.GetVar(ctx, fmt.Sprintf(transactionListInfoURL, client.url), param).Scan(&detailData)
	return
}
